/**
 *  window.cpp
 *  ASEngine
 *
 *	Date: 07/08/2013
 *
 *	Language: C++
 *
 *  @author Carl McCaffrey
 *
 */
#include "renderer/window.h"
#include <stdio.h>

DEVMODE defaultSettings, fullscreenSettings;
bool fullScreen;

bool Window::Create(HINSTANCE* hinstance, XMFLOAT2 winsize, unsigned int flags)
{
	printf("Creating Window...\n");
	hInstance = hinstance;
	if(winsize.x != NULL){
		size = winsize;
	}else{
		size.x = static_cast<float>(GetSystemMetrics(SM_CXSCREEN));
		size.y = static_cast<float>(GetSystemMetrics(SM_CYSCREEN));
	}

	if(flags & WINDOW){
		fullscreen = fullScreen = false;
	}else if(flags & FULLSCREEN){
		fullscreen = fullScreen = true;
	}

	WNDCLASSEX wndClass = { NULL };
	wndClass.lpszClassName = "window";
	wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = Window::WndProc;
	wndClass.hInstance = *hinstance;
	wndClass.hIcon = (HICON)LoadImage(GetModuleHandle(NULL), "HF/Resources/icon.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
	wndClass.hIconSm = NULL;
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndClass.lpszMenuName = NULL;
	wndClass.cbSize = sizeof(wndClass);

	if(!RegisterClassEx(&wndClass)){
		printf("\tFailed To Register Window!\n");
		return false;
	}

	DWORD wndStyle;
	DWORD wndStyleEx;

	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &defaultSettings);
	if(fullscreen){
		memset(&fullscreenSettings, NULL, sizeof(DEVMODE));
		fullscreenSettings.dmSize = sizeof(DEVMODE);
		fullscreenSettings.dmPelsWidth = static_cast<DWORD>(size.x);
		fullscreenSettings.dmPelsHeight = static_cast<DWORD>(size.y);
		fullscreenSettings.dmBitsPerPel = 32;
		fullscreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		if(ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL){
			wndStyle = WS_POPUP;
			wndStyleEx = WS_EX_APPWINDOW;
			printf("\tEntered Full Screen Mode!\n");
		}else{
			if(MessageBox(hWnd, "Failed To Enter Full Screen Mode!\nRun In Windowed Mode?", "Warning", MB_ICONWARNING | MB_YESNO) == IDYES){
				wndStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU;
				wndStyleEx = WS_EX_APPWINDOW;
				fullscreenSettings = defaultSettings;
				fullscreen = fullScreen = false;
				printf("\tEntered Windowed Mode\n");
			}else{
				return false;
			}
		}
	}else{
		wndStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU;
		wndStyleEx = WS_EX_APPWINDOW;
		fullscreenSettings = defaultSettings;
	}

	RECT wndRect = { 0, 0, static_cast<long>(size.x), static_cast<long>(size.y) };
	AdjustWindowRectEx(&wndRect, wndStyle, FALSE, wndStyleEx);

	hWnd = CreateWindowEx(wndStyleEx, "window", "Window", wndStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, wndRect.right - wndRect.left, wndRect.bottom - wndRect.top, NULL, NULL, *hInstance, NULL);
	if(!hWnd){
		printf("Failed To Create Window!\n");
		return false;
	}

	ShowWindow(hWnd, SW_SHOW);
	SetForegroundWindow(hWnd);
	SetFocus(hWnd);
	printf("Window Created!\n");

	return true;
}

void Window::Destroy(void)
{
	printf("Destroying Window!\n");
	CursorVisible(true);
	ChangeDisplaySettings(&defaultSettings, NULL);
	DestroyWindow(hWnd);
	UnregisterClass("window", *hInstance);
	*hInstance = NULL;
}

void Window::SetTitle(const char* title)
{
	SetWindowText(hWnd, title);
}

void Window::CursorVisible(bool visible)
{
	ShowCursor(visible);
}

bool Window::GetFullScreen(void)
{
	return fullscreen;
}

bool Window::CursorVisible(void)
{
	return cursor;
}

HWND Window::GetHandle(void)
{
	return hWnd;
}

XMFLOAT2 Window::GetSize(void)
{
	return size;
}

LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hDC;

	switch(msg)
	{
		case WM_PAINT:
			hDC = BeginPaint(hwnd, &ps);
			EndPaint(hwnd, &ps);
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
			break;

		case WM_SYSCOMMAND:
			switch(wParam){
				case SC_SCREENSAVE:
				case SC_MONITORPOWER:
					return 0;
			}
			break;

		case WM_KEYDOWN:
			if(wParam == VK_ESCAPE)
				PostQuitMessage(0);
			break;

		case WM_SETFOCUS:
			if(fullScreen){
				ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN);
				ShowWindow(hwnd, SW_SHOW);
				printf("\nWindow Maximized!\n");
			}
			break;

		case WM_KILLFOCUS:
			if(fullScreen){
				ChangeDisplaySettings(&defaultSettings, NULL);
				ShowWindow(hwnd, SW_SHOWMINIMIZED);
				printf("\nWindow Minimized!\n");
			}
			break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}
